FORM TDDD - Imagine 3D object file format ----------------------------------------- Date: 23 Feb 1998 Imagine: Covered through version 1.3.x for Windows (includes previous versions for DOS PC and Amiga) Imagine object files are written in an "IFF standard" file format. "FORM TDDD" refers to the particular type of data that it contains, and the format it is presented in. The full IFF specification provides a wide variety of options for formatting data. A "FORM" block is one of the options. However, most, if not all, IFF files contain one or more FORM blocks. A FORM block has a "type identifier" (TDDD, in this case), and data within a FORM block is interpreted according to its type. FORM TDDD was originally used by FORM TDDD is used by Impulse's "Turbo Silver 3.0". At that time, it was used regurlarly, to store multiple 3D object heirarchies, as well as camera and environment information. And the data for an animation consisted of a series of TDDD files ... which sometimes included references to other files, containing single objects or object heirarchies. Currently, it is used only to store only a single object heirarchy. As a result, the file format may seem a little "over complicated". IFF details ----------- ** important -- byte ordering and even-size padding ** The IFF specification was originally developed for machines running on Motorola CPUs, where "multi-byte" numeric data (e.g. 32-bit integers) is stored with the most significant byte appearing first. When IFF files are read and written on "PC compatible" machines, which store the bytes in the opposite order, special care must be taken to reverse the byte ordering for numberic data. In this way, the files are kept "binary compatible" across machine platforms. The layout of IFF files is defined with special care taken to ensure that IFF file readers can skip over blocks of data that they don't understand, or don't care about. "Blocks" and "chunks" of data all have 4-character identifiers followed by a 32-bit size field, followed by a block of data of the given size. When the 4-character identifier is not recognized, the data can be skipped by using the number appearing in the size field. There is one important "special case" for size fields. When the size is odd, one extra byte (a zero) is written following the data, to pad it to a 2-byte boundary. That fact must be kept in mind when reading and writing data, and when skipping over unrecognized data. A FORM block has the following layout: +-------------------+---------------------------------------------- 0 | 'F' 'O' 'R' 'M' | identifies block as a FORM block | | 4 | 32-bit size (N) | specifies size of data following size field +-------------------+---------------------------------------------- 8 | 'T' 'D' 'D' 'D' | FORM type identifier (TDDD in this case) +-------------------+ | | | data chunk | data unique to TDDD | | +-------------------+ | | | data chunk | data unique to TDDD | | +-------------------+ | | | ... etc. | | | +-------------------+ | | | data chunk | | | (end of FORM block) +-------------------+----------------------------------------------- N+8 A data "chunk" has the following layout: +-------------------+---------------------------------------------- 0 | 'S' 'I' 'Z' 'E' | chunk type identifier ('SIZE' in this case) | | 4 | 32-bit size (N) | specifies size of data following size field +-------------------+---------------------------------------------- | | | N bytes of data | data for SIZE block | | +-------------------+---------------------------------------------- N+8 | (trailing zero) | if required for even byte padding +-------------------+---------------------------------------------- N+8 or N+9 (whichever is even) TDDD chunk types ---------------- In current TDDD files, there is only one chunk type that is used. Its identifier is 'OBJ ', and the data inside it describes a single object heirarchy. In older files, multiple 'OBJ ' chunks could appear, as well as other chunk types. (An "object heirarchy" is a parent object, with nested ("grouped") child objects ... where each child can have child objects of its own, and so on.) In TDDD files, the general "IFF" structure has been extended to include "chunks within chunks". The data in an 'OBJ ' chunk, then, is composed of a series of sub-chunks, each having the form of an IFF chunk -- with a 4-character identifier followed by the data size, followed by the data itself, followed by a (zero) pad byte if necessary, to align the data with an even byte boundary. Similarly, then, one of the chunks types that appears in an 'OBJ ' chunk, is a 'DESC' chunk -- and it is composed itself, of more sub-chunks. It is the chunks appearing in a DESC chunk, contain the "real data" for the objects. 'OBJ ' chunk ------------ And 'OBJ ' chunk is composed of only two "sub-chunk" types. A 'DESC' chunk, and a 'TOBJ' chunk. Multiple chunks of each type can appear, and each DESC chunk is matched with a "closing" TOBJ chunk, appearing after, somewhere, it in the data. The main use of the two chunk types is to describe the grouping structure of the object heirarchy. The 'DESC' chunks contain data describing each object (parent or child). Following the 'DESC' chunk for a given object, is data for each of its child objects. And following that is a 'TOBJ' chunk, that marks the end of the child object data, and the end of the heirarchy introduced by the 'DESC' chunk. The child object data itself, is a series 'DESC' and chunks with matching (closing) 'TOBJ' chunks. So the data for a parent object with two child objects would have the form: (DESC,(DESC,TOBJ),(DESC,TOBJ),TOBJ) - parent with 2 child objects A 'TOBJ' chunk has no data (its size field is zero), and serves only to mark the end of the child object data, for a given object. A 'DESC' chunk is composed of smaller sub-chunks, that describe the object's geometry and other properties. Summary of above ---------------- With the above facts in mind, the layout of a "current" FORM TDDD file is as follows: +---------------------+------------------------------------------ 0 | 'F' 'O' 'R' 'M' | identifies block as a FORM block | | 4 | 32-bit size (N+M+28)| size of data following the size field +---------------------+------------------------------------------ 8 | 'T' 'D' 'D' 'D' | FORM type identifier +---------------------+----------------------------------- 12 | 'O' 'B' 'J' | | | 'OBJ ' chunk header 16 | 32-bit size (N+M+16)| +---------------------+----------------------------------- 20 | 'D' 'E' 'S' 'C' | | | 'DESC' sub-chunk header 24 | 32-bit size (N) | +---------------------+-------------------------- 28 | | | data chunk | object data | | +---------------------+ | | | data chunk | object data | | +---------------------+ | | | ... etc. | | | +---------------------+ | | | data chunk | | | (end of DESC chunk) +---------------------+-------------------------- N+28| | | child object data | matching 'DESC' and 'TOBJ' pairs | (M bytes) | (maybe with more nested pairs) +---------------------+-------------------------- N+28| | +M | 'T' 'O' 'B' 'J' | 'TOBJ' sub-chunk (header) | | | 0 (zero) | (end of 'TOBJ', 'OBJ ', and FORM block) +---------------------+------------------------------------------ N+M+36 DESC data - chunks appearing within DESC chunks ----------------------------------------------- This is the "core" of the file format specificaton. The chunk types appearing in DESC chunks have changed over the years, as more features have been added to Imagine. Imagine continues to read the older style data, but writes its output in the newer forms. All of the types are described below. The descriptions are broken into sections describing geometry related data, attribute related data, special object data, and object "state" data. Imagine version note: As of this writing (Feb, '98), Imagine 1.3 is available as part of Impulse's "constant upgrade program". It is the only version that reads and writes the newer style chunks that support point edge and face counts larger than 32K. Up until that point, the parts of the file format related to the "geometry" of objects, had remained largly unchanged. As a result, older versions of the software have at least been able to read the geometry correctly. With the "> 32K" changes, that is no longer the case. If you want to write TDDD files readable by "most" current Imagine users, you should stick to the "pre-1.3" style chunks. The 1.3 style chunks will be readable in all future versions of Imagine, however ... so you can certainly use them. But, you should take care to inform users that Imagine 1.3 or higher will be required. Other version notes: When Imagine was introduced for the Windows platform, the version numbering was changed back to 1.0. The text below, may refer to versions 3.0, etc, for DOS PC, and Amiga. These versions precede the Windows version. There are some conventions that are always used, below: Floating point data is always converted to a "fixed point" representation, and written as a 32-bit integer (byte reversed as appropriate). The conversion algorithm is as follows: to integer: if (f < 0) n = -(int)(-65536.0 * f + 0.5); else n = (int)(65536.0 * f + 0.5); to floating point: f = n / 65536.0; The resulting data is independent of any particular floating point representation, but has a limitation that it can only properly store floating point numbers in the range of -32767.5 < f < 32767.5 The data type 'FRACT' (below), is used to indicate floating point numbers which have been converted to the fixed point integer representation. Other data types: BYTE - unsigned character WORD - unsigned 16-bit integer DWORD - unsigned 32-bit integer SHORT - signed 16-bit integer LONG - signed 32-bit integer typedef LONG FRACT; // 4 bytes typedef struct { FRACT X; // 4 bytes FRACT Y; // 4 bytes FRACT Z; // 4 bytes } VECTOR; // 12 bytes total typedef struct { VECTOR I; // 12 bytes VECTOR J; // 12 bytes VECTOR K; // 12 bytes } MATRIX; // 36 bytes total typedef struct { VECTOR r; // 12 bytes - position VECTOR a; // 12 bytes - x axis direction (unit vector) VECTOR b; // 12 bytes - y axis direction (unit vector) VECTOR c; // 12 bytes - z axis direction (unit vector) VECTOR s; // 12 bytes - size (axis lengths) } TFORM; // 60 bytes total // #pragma pack(1) typedef BYTE COLOR[3]; // 3 bytes - 1st byte = R, 2nd = G, 3rd = B // #pragma pack() ** Note ** use of the COLOR type is not recommended, due to potential problems with byte packing and data alignment in the compiler. It is used only as a convention in this document. [An older version of one C compiler, produced a difficult bug to track down at Impulse. It was eventually discovered that copying COLOR values using pointers of type (COLOR *) resulted in 4 bytes (not 3) being copied -- yet incrementing the pointers caused them to change by 3 bytes]. DESC sub-sub-chunks - geometry related -------------------------------------- Some of these fields are optional, and defaults values are used. A SHAP or SHP2 chunk MUST be present. Defaults are: illegal shape; positioned at (0,0,0); axes aligned to the world axes; size fields all 32.0; SHAP - size 4 Note: This has been superceded by 'SHP2', below, as of Imagine version 3.0 for the DOS PC and Amiga (includes Imagine for Windows version 1.0) WORD Shape; ; number indicating object type WORD Lamp; ; number indicating lamp type Lamp numbers are composed of several bit fields: Bits 0-1: 0 - not a lamp 1 - like sunlight 2 - like a lamp - intensity falls off with distance. 3 - unused/reserved Bits 2: 0 - non-shadow-casting light 4 - shadow-casting light Bits 3-4: 0 - Spherical light source 8 - Cylindrical light source. 16 - Conical light source. 24 - unused/reserved Shape numbers are: 0 - Sphere ; "perfect sphere", not point based. 1 - Stencil ; - obsolete 2 - Axis ; "normal" objects with points/triangles 3 - Facets ; illegal - for internal use only 4 - Surface ; - obsolete 5 - Ground ; "infinite plane", not point based. Spheres have thier radius set by the X size parameter. Stencils and surfaces are plane-parallelograms, with one point at the object's position vector; one side lying along the object's X axis with a length set by the X size; and another side starting from the position vector and going "Y size" units in the Y direction and "Z size" units in the X direction. A ground object is an infinte plane perpendicular to the world Z axis. Its Z coordinate sets its height, and the X and Y coordinates are only relevant to the position of the "hot point" used in selecting the object in the editor. Custom objects have points, edges and triangles associated with them. The size fields are relevant only for drawing the object axes in the editor. Shape number 3 is used internally for triangles of custom objects, and should never appear in a data file. SHP2 - size 4 Note: Replaces SHAP, above, as of Imagine version 3.0 for the Amiga and DOS PC WORD Shape; ; number indicating object type WORD Lamp; ; number indicating lamp type Shape numbers are: 0 - Sphere ; perfect sphere object 2 - Axis ; custom objects with points/triangles 5 - Ground ; infinite horizontal plane Spheres have thier radius set by the X size parameter. Grounds have thier graphical size set by the X and Y size parameters. Lamp numbers are composed of several bit fields: (note the bit definitions have changed - from the definition of the bits in the (older) SHAP chunk) Bits 0-1: (type bits) 0 - not a light source 1 - point light source 2 - parallel ray light source 3 - unused/reserved Bits 2-3: (shape bits) 0 - no shape (spherical radiator) 4 - round light 8 - rectangular light 12 - unused/reserved Bit 4: (lens flare bit) 0 - normal 16 - "No lens flare" - for use by Lens Flare global F/X Bits 5-6: (falloff bits) 0 - no falloff 32 - (1/R) falloff 64 - "controlled" falloff 96 - (1/R**2) falloff Bit 7: (shadow bit) 0 - doesn't cast shadows 128 - casts shadows Bit 8: (soft shadows bit) 0 - normal 256 - casts "soft shadows" (if bit 7 set) Bit 15: (bright object bit) 0 - normal object 32768 - "bright object" (fully bright) Note: variable brightness was added, and if the "bright" bit is seen on input, Imagine sets the brightness value to 255, and clears this bit ... it is no longer written by Imagine. POSI - size 12 VECTOR Position; ; the object's position. Legal coordinates are in the range -32768 to 32767 and 65535/65536. Currently, the ray-tracer only sees objects in the -1024 to 1024 range. Light sources, and the camera may be placed outside that range, however. AXIS - size 36 VECTOR XAxis; VECTOR YAxis; VECTOR ZAxis; These are direction vectors for the object coordinate system. They must be "orthogonal unit vectors" - i.e. the sum of the squares of the vevtor components must equal one (or close to it), and the vectors must be perpendicular. SIZE - size 12 VECTOR Size; See SHAP chunk above. The sizes are used in a variety of ways depending on the object shape. For custom objects, they are the lengths of the coordinate axes drawn in the editor. If the object has its "Quickdraw" flag set, the axes lengths are also used to set the size of a rectangular solid that is drawn rather than drawing all the points and edges. PNTS - size 2 + 12 * point count PNT2 - size 4 + 12 * point count - 32K limit removed (PNTS chunk) WORD PCount; ; point count VECTOR Points[]; ; points (PNT2 chunk) - DWORD count DWORD PCount; ; point count VECTOR Points[]; ; points This chunk has all the points for faceted objects. They are refered to by thier position in the array ... with the first point being point number zero. EDGE - size 2 + 4 * edge count EDG2 - size 4 + 8 * edge count - 32K limit removed (EDGE chunk) WORD ECount; ; edge count WORD Edges[][2]; ; edges (EDG2 chunk) DWORD ECount; ; edge count DWORD Edges[][2]; ; edges This chunk contins the edge list for faceted objects. The Edges[][2] array is pairs of point numbers that are connected by the edges. Edges are refered to by thier position in the Edges[] array ... with the first edge being edge number zero. FACE - size 2 + 6 * face count FAC2 - size 4 + 12 * face count - 32K limit removed (FACE chunk) WORD TCount; ; face count WORD Connects[][3]; ; faces (FAC2 chunk) DWORD TCount; ; face count DWORD Connects[][3]; ; faces This chunk contains the triangle (face) list for custom objects. The Connects[][3] array is triples of edge numbers that are connected by triangles. Note: See intro to "Attribute related" data -- to remain compatible with older versions of Imagine, you should write "per face" data for color/reflect/filter values, if you write this chunk. BBOX - size 24 VECTOR Mins; ; minimum X,Y,Z values in local coordinates VECTOR Maxs; ; maximum X,Y,Z values in local coordinates This chunk contains bounding box data for the object. It is used in Imagine when the stage editor is set to "Quick Draw" mode ... where in switching between frames, the point data for objects is ignored, and they are treated as simple bounding boxes. DESC sub-sub-chunks - attribute related --------------------------------------- Most of these fields are optional, and defaults are supplied. However, if there is a FACE chunk, there must also be a CLST chunk, an RLST chunk and a TLST chunk -- all with matching "count" fields. (This restriction is relaxed in newer versions of Imagine, but to remain compatible with older versions, Imagine always writes this data ... is may not, in the future, though, since with the introduction of the new chunk types supporting point edge and face chunks larger than 32K, the older software shouldn't have trouble, since it won't recognize the geometry chunks anyway). Defaults are: Colors set to (255,255,255); reflection and transmission coefficients set to zero; illegal shape; positioned at (0,0,0); axes aligned to the world axes; size fields all 32.0; light source intensity at (255.0,255.0,255.0); no name; no points/edges or faces; refractive index 1.00; phong shaded; brightness, hardness roughness, and shininess set to zero; not a light source; not brightly lit; NAME - size 18 BYTE Name[18]; ; a name for the object (null terminated) Used for camera tracking, specifying path names, etc. You should always assign a name to the object in the file. Imagine displays the name in its "Find" object dialog. You don't need to specify a unique name for each object. When Imagine loads the objects, it will alter the name, if there is already an object with the same name. COLR - size 4 REFL - size 4 TRAN - size 4 SPC1 - size 4 - superceded by SPC2, below. BYTE Pad; ; pad byte - must be zero COLOR Color; ; RGB color These are the main object RGB color, and reflection, transmission and specularity coefficients. SPC2 - size 8 Note: This supercedes by SPC2 as of Imagine version 1.3 for Windows. BYTE Pad; ; pad byte - must be zero COLOR Color; ; RGB color FRACT Overdrive; ; specular overdrive setting INT1 - size 12 VECTOR Intensity; ; light source intensity Light source intensity. The vector components hold the (separate) R, G and B intensities. The X component is the R intensity, Y is G, and Z is B. CLST - size 2 + 3 * count CLS2 - size 4 + 3 * count - 32K limit removed RLST - size 2 + 3 * count RLS2 - size 4 + 3 * count - 32K limit removed TLST - size 2 + 3 * count TLS2 - size 4 + 3 * count - 32K limit removed (CLST,RLST and TLST chunks) WORD count; ; count of colors (faces) COLOR colors[]; ; colors (CLS2,RLS2 and TLS2 chunks) DWORD count; ; count of colors (faces) COLOR colors[]; ; colors (note: odd chunk size is possible) These are the color, reflection and transmission coefficients for each face in custom objects. The count should match the face count in the FACE chunk. The ordering corresponds to the face order. As always, when the chunk size is odd, it is followed by a zero pad byte. EFLG - size 2 + count EFL2 - size 4 + count - 32K limit removed (EFLG chunk) WORD count; ; count of flag bytes (edges) BYTE flags[]; ; flag bytes (EFL2 chunk) LONG count; ; count of flag bytes (edges) BYTE flags[]; ; flag bytes Edge attributes ("per edge" flags). The flag bits are defined as: bits 0-5 - reserved, set to zero. bit 6 - "quick" edge - used with "quick edges" drawing mode bit 7 - "sharp" edge - disables Phong shading across the edge Imagine writes this chunk only when at least one edge has at least one flag bit set (when it would not be a block of zeros). As always, when the chunk size is odd, it is followed by a zero pad byte. PRP1 - size 8 - superceded PRP2 - size 8 - supercedes PRP1 BYTE IProps[8]; ; more object properties This chunk contains object properties that programs other than Imagine might support. (for PRP1 chunk) IProps[0] - IPRP_DITHER ; blending factor (0-255) (obsolete) IProps[1] - IPRP_HARD ; hardness factor (0-255) IProps[2] - IPRP_ROUGH ; roughness factor (0-255) IProps[3] - IPRP_SHINY ; shinyness factor (0-255) IProps[4] - IPRP_INDEX ; index of refraction IProps[5] - IPRP_QUICK ; flag - Quickdraw on/off IProps[6] - IPRP_PHONG ; flag - Phong shading on/off IProps[7] - IPRP_GENLOCK ; flag - Genlock on/off (obsolete) (for PRP2 chunk) IProps[0] - IPRP_BRIGHT ; brightness factor (0-255) IProps[1-7] - same as above. The hardness factor controls how tight the specular spot should be - 0 is a big soft spot, 255 is a tight hot spot The roughness factor controls how rough the object should appear - 0 is smooth, 255 is max roughness. The shiny factor in interaction with the object's filter values controls how shiny the object appears. Setting it to anything but zero forces the object to be non-transparent since then the filter values are used in the shiny (reflection) calculations. A value of 255 means maximum shininess. The brightness factor refers controls how much lighting and light sources affect the object's rendered "color". When the brightness is zero, the normal lighting algorithms are used. When it is 255, the lighting calculations are ignored, and the object appears "bright" in the rendering, with the colors taken directly from the object. Intermediate values result in a blend of the "shaded" and "bright" appearance. FOGL - size 4 FOG2 - size 14 - Imagine for Windows 1.2 FOG3 - size 18 - Imagine for Windows 1.3 These chunks contain data for "fog objects". (FOGL chunk) FRACT Length; ; fog length attribute (FOG2 chunk) FRACT Length; ; fog length attribute FRACT Falloff; ; falloff distance FRACT Hot; ; fog "hotness" setting WORD Type; ; fog type (bits) (FOG3 chunk) FRACT Length; ; fog length attribute FRACT Falloff; ; falloff distance FRACT Hot; ; fog "hotness" setting FRACT Overdrive; ; fog "overdrive" setting WORD Type; ; fog type (bits) Fog Type bits: bits 0-1: falloff type 0 - no falloff 1 - radial falloff 2 - axial falloff 3 - planar falloff bits 2-3: falloff axis 0 - X axis 4 - Y axis 8 - Z axis bit 7: "hot center" on/off 0 - off 128 - on BLB2 - size 10 "Blob" object attributes FRACT Strength; ; blob strength - default is 1.0 FRACT Threshold; ; unused - Imagine writes 0.6 in FRACT form. WORD MeshDensity; ; mesh density The MeshDensity setting is ignored for all but the head object of a group of blob objects. The entire group (generally) gets converted into a single faceted object, using the MeshDensity setting from the head object. PART - size 6 - obsolete PAR2 - size 8 - supercedes PART in Imagine 3.1 for DOS PC and Amiga (PART chunk) WORD Type; ; type bits FRACT Size; ; "particle size" setting (PAR2 chunk) DWORD Type; ; type bits FRACT Size; ; "particle size" setting Particle attributes. The exact reason for the two chunk types, is uncertain. The new chunk type may have been added as part of a bug fix. The Type bits have the same meaning in both cases. Type bits: bits 0-3 - particle type 0 - no particles - normal object 1 - tetrahedrons 2 - pyramids 3 - octahedrons 4 - cubes 5 - blocks (rectangular solids) 6 - dodecahedrons 7 - spheres 8 - randomly chosen, per face, from the list above 9 - filename - a PTFN chunk should be present too. bits 4-7 - centering option 0x00 - inscribed 0x10 - circumscribed 0x20 - interpolated 0x30 - barycentric bits 8-11 - sizing option 0x000 - small 0x100 - large 0x200 - random 0x300 - specify (use size value) bits 12-15 - alignment option 0x0000 - align to object 0x1000 - align to faces 0x2000 - random PTFN - variable size - (1 + strlen(particle_filename)) BYTE CharCount; ; count of characters in filename BYTE[] FileName; ; - not null terminated Particle file name. Specifies the name of a TDDD object file, for use with particlization. The chunk size is one plus the length of the string. As always, when the chunk size is odd, it is followed by a zero pad byte. FGRP - size 20 + 2 * count FGR2 - size 26 + 2 * count + variable size -- Imagine 3.0 (DOS,Amiga) FGR3 - size 28 + 2 * count + variable size -- Imagine 3.1 (DOS,Amiga) FGR4 - size 30 + 4 * count + variable size -- Imagine for Windows 1.3 the 'variable size' is (1 + strlen(particle_filename)) These chunks describe data for "face subgroups" ... i.e. named lists of faces, by face number. The change from FGRP to FGRP2 and higher, came when subgroups could have "particle attributes" assigned to them. The change to FGRP3 corresponts to the change from PART to PAR2. The change to FGRP4 allows for face numbers greater than 32K, and for subgroups to have > 32K faces. The variable sized field at the end is for a user specified particle file name (a TDDD file). It consists of a byte count, followed by the filename characters, with no null termination. (FGRP chunk) WORD Count; ; count of faces in subgroup BYTE Name[18]; ; null terminated name string WORD FaceList[]; ; list of face numbers (0 based) (FGR2 chunk) WORD Count; ; count of faces in subgroup BYTE Name[18]; ; null terminated name string WORD FaceList[]; ; list of face numbers (0 based) WORD PType; ; particle type bits - see PART/PAR2 FRACT PSize; ; particle size BYTE Count; ; filename length BYTE FileName[]; ; particle filename - not null terminated (note: odd chunk size is possible) (FGR3 chunk) WORD Count; ; count of faces in subgroup BYTE Name[18]; ; null terminated name string WORD FaceList[]; ; list of face numbers (0 based) DWORD PType; ; particle type bits - see PAR2 FRACT PSize; ; particle size BYTE Count; ; filename length BYTE FileName[]; ; particle filename - not null terminated (note: odd chunk size is possible) (FGR4 chunk) DWORD Count; ; count of faces in subgroup (32 bit) BYTE Name[18]; ; null terminated name string DWORD FaceList[]; ; list of face numbers (0 based, 32 bit) DWORD PType; ; particle type bits - see PAR2 FRACT PSize; ; particle size - see PAR2 BYTE Count; ; filename length BYTE FileName[]; ; particle filename - not null terminated (note: odd chunk size is possible) See the PART/PAR2 and PTFN descriptions for details on the particlization data. As always, when the chunk size is odd, it is followed by a zero pad byte. BBSG - size 18 SBSG - size 18 BYTE Subgroup[18] ; null terminated subgroup name These chunks list the "big" and "small" bones subgroup names, for use with Imagine's "bones" feature. TXT1 - size 142 + variable size - Imagine 1.0 for DOS PC and Amiga TXT2 - size 160 + variable size - Imagine 1.1 for DOS PC and Amiga TXT3 - size 178 + variable size - Imagine 3.0 for DOS PC and Amiga TXT4 - size 200 + variable size - Imagine 3.3 for DOS PC and Amiga the 'variable size' is (1 + strlen(module_filename)) These chunks contain data for algorithmic textures. (TXT1 chunk) WORD Flags; ; texture flags TFORM TForm; ; local coordinates of texture axes. FRACT Params[16]; ; texture parameters BYTE PFlags[16]; ; parameter flags (currently unused) BYTE Length; ; length of texture file name BYTE Name[Length]; ; texture file name (not NULL terminated) (note: odd chunk size is possible) (TXT2 chunk) WORD Flags; ; texture flags TFORM TForm; ; local coordinates of texture axes. FRACT Params[16]; ; texture parameters BYTE PFlags[16]; ; parameter flags (currently unused) BYTE Subgrp[18]; ; subgroup name, for "restrict to subgroup" BYTE Length; ; length of texture file name BYTE Name[Length]; ; texture file name (not NULL terminated) (note: odd chunk size is possible) (TXT3 chunk) WORD Flags; ; texture flags TFORM TForm; ; local coordinates of texture axes. FRACT Params[16]; ; texture parameters BYTE PFlags[16]; ; parameter flags (currently unused) BYTE Subgrp[18]; ; subgroup name, for "restrict to subgroup" BYTE Stname[18]; ; "tacking" state name - NULL terminated BYTE Length; ; length of texture file name BYTE Name[Length]; ; texture file name (not NULL terminated) (note: odd chunk size is possible) (TXT4 chunk) WORD Flags; ; texture flags: TFORM TForm; ; local coordinates of texture axes. FRACT Params[16]; ; texture parameters BYTE PFlags[16]; ; parameter flags (currently unused) BYTE Subgrp[18]; ; subgroup name, for "restrict to subgroup" BYTE Stname[18]; ; "tacking" state name - NULL terminated BYTE Label[18]; ; User label - NULL terminated FRACT Mixing; ; "mixing intensity" (0...1) - default 1.0 BYTE Length; ; length of texture file name BYTE Name[Length]; ; texture file name (not NULL terminated) (note: odd chunk size is possible) As always, when the chunk size is odd, it is followed by a zero pad byte. The Flags bit are: 1 (bit 0) - TXTR_CHILDREN - apply texture to child objects in group 2 (bit 1) - TXTR_LIGHTING - the texture is a "lighting texture" 4 (bit 2) - TXTR_DISABLE - the texture is disabled (ligting textures are used with objects that are light sources) The 'Params' block stores up to 16 "floating point" values, that act as parameters for the texture. Unused values should contain zeros. The 'PFlags' bits, one for each parameter, are used by Imagine for performing "special services" with texture parameters. 1 (bit 0) - TXTF_RED - indicates Red RGB value in 0.0-255.0 range 2 (bit 1) - TXTF_GRN - indicates Green value in 0.0-255.0 range 4 (bit 2) - TXTF_BLU - indicates Blue value in 0.0-255.0 range 8 (bit 3) - TXTF_SCL - indicates a parameter that scales in proportion to the object, when the object is resized (in all 3 axes). 16 (bit 4) - TXTF_UNUSED - for DOS/Amiga textures only (interface) 32 (bit 5) - TXTF_LUNUSED - for DOS/Amiga textures only (interface) These flags are specified by the texture modules themselves, when a texture is first placed on an object, and after that they never change. Originally, with the exception of the 'TXTF_SCL' flag, the flags were used to control the dialog that Imagine set up for the texture modules. As of the Windows version, the texture modules are largely responsible for thier own interface. However, as of the Imagine 1.2 for Windows, the TXTF_RED,GRN,BLU flags are also used in rendering, to identify RGB values and apply an "inverse" gamma correction to them, prior to rendering. The texture modules manage and store RGB values as set in the interface, in these locations, and then Imagine may alter them prior to calling the texture during rendering, depending on the users preferences. (Note: for texture designers - failure to set the RGB flags for, RGB color parameters will usually result in rendered colors appearing hue shifted with respect to what the user sets up in the interface - primary colors are an exception) BRS1 - 64 + variable size - Imagine version 1.0 for DOS PC and Amiga BRS2 - 68 + variable size - Imagine version 1.1 for DOS PC and Amiga BRS3 - 86 + variable size - Imagine version ?? BRS4 - 104 + variable size - Imagine 3.0 for DOS PC and Amiga BRS5 - 134 + variable size - Imagine 3.3 for DOS PC and Amiga the 'variable size' is (1 + strlen(brush_filename)) These chunks contain data for brush maps. (BRS1 chunk) WORD Flags; ; brush type: WORD WFlags; ; brush wrapping flags: TFORM TForm; ; local coordinates of brush axes. BYTE Length; ; length of brush file name BYTE FileName[]; ; brush file name (not null terminated) (note: odd chunk size is possible) (BRS2 chunk) WORD Type; ; brush type WORD WFlags; ; brush wrapping flags TFORM TForm; ; local coordinates of brush axes. WORD FullScale; ; full scale value WORD MaxSeq; ; highest number for sequenced brushes BYTE Length; ; length of brush file name BYTE FileName[]; ; brush file name (not null terminated) (note: odd chunk size is possible) (BRS3 chunk) WORD Type; ; brush type: WORD WFlags; ; brush wrapping flags: TFORM TForm; ; local coordinates of brush axes. WORD FullScale; ; full scale value WORD MaxSeq; ; highest number for sequenced brushes BYTE Subgrp[18]; ; subgroup name, for "restrict to subgroup" BYTE Length; ; length of brush file name BYTE FileName[]; ; brush file name (not null terminated) (note: odd chunk size is possible) (BRS4 chunk) WORD Type; ; brush type: WORD WFlags; ; brush wrapping flags: TFORM TForm; ; local coordinates of brush axes. WORD FullScale; ; full scale value WORD MaxSeq; ; highest number for sequenced brushes BYTE Subgrp[18]; ; subgroup name, for "restrict to subgroup" BYTE Stname[18]; ; "tacking" state name - NULL terminated BYTE Length; ; length of brush file name BYTE FileName[]; ; brush file name (not null terminated) (note: odd chunk size is possible) (BRS5 chunk) WORD Type; ; brush type: WORD WFlags; ; brush wrapping flags: TFORM TForm; ; local coordinates of brush axes. WORD FullScale; ; full scale value WORD MaxSeq; ; highest number for sequenced brushes BYTE Subgrp[18]; ; subgroup name, for "restrict to subgroup" BYTE Stname[18]; ; "tacking" state name - NULL terminated BYTE Label[18]; ; User label - NULL terminated FRACT Mixing; ; "mixing intensity" (0...1) - default 1.0 FRACT FogLo; ; minimum fog length - for fog brushes FRACT FogHi; ; maximum fog length - for fog brushes BYTE Length; ; length of brush file name BYTE FileName[]; ; brush file name (not null terminated) (note: odd chunk size is possible) brush type values: 0 Color map 1 Reflectivity map 2 Filter map 3 Altitude map 4 Reflection (Environment) map 5 Specular map 6 Hardness map 7 Roughness map 8 Fog length map 9 Shininess map 10 Brightness map 11 Index of refraction map 12 Light (ambient) map brush wrapping flags: 1 WRAP_X - wrap type 2 WRAP_Z - wrap type 4 WRAP_CHILDREN - apply to children 8 WRAP_REPEAT - repeating brush 16 WRAP_FLIP - flip with repeats 32 WRAP_INVERT - use "inverse video" 64 WRAP_ZEROCOLOR - don't apply brush in "color zero" area 128 WRAP_DISABLE - brush is disabled DESC sub-sub-chunks - specialized object data --------------------------------------------- DTOO - size 4 BYTE Type; ; type of deform tool - always 1 BYTE NX; ; # of points in X direction (>= 2) BYTE NY; ; # of points in Y direction (>= 2) BYTE NZ; ; # of points in Z direction (>= 2) This chunk appears when Imagine "deform tool" objects are written. The numbers, NX, etc, are one larger than the "section" counts that the user specifies in the deform tool creation dialog. It was introduced in the Windows 1.1 upgrade version. The point count for the object is NX * NY * NZ (when the type is 1). Prior to the introduction of this chunk, when Imagine created a deform tool it have it a name like 'DTOOL_2_2_4', to describe a tool with NX=3,NY=3, and NZ=5, above. As a result, it did not recognize such an object as a deform tool, if the user had changed the name of the object. PTHD - size 2 + 60 * axis count PTH2 - size 2 + 68 * axis count - (spline editor added) PTH3 - size 4 + 76 * axis count - Imagine 1.3 for Windows These chunks contain the data for Imagine "path" objects. PTH2 and PTH3 chunks are used for "spline editor" paths as well as "detail" and "stage editor" (axis based) paths. (PTHD chunk) WORD ACount; ; axis count TFORM PData[]; ; axis data (PTH2 chunk) WORD ACount; ; axis count PTHD_OLD PData[]; ; axis data (PTH3 chunk) - 32K limit removed DWORD ACount; ; axis count PTHD PData[]; ; axis data The PTHD and PTHD_OLD structures are defined as: typedef struct { VECTOR r; ; position of axis (spline "knot") VECTOR a; ; direction 1 VECTOR b; ; direction 2 VECTOR c; ; direction 3 VECTOR s; ; sizes LONG infrom; ; axis number for "from" connection LONG outto; ; axis number for "to" connection LONG flags; ; see below. LONG extracnt; ; reserved - must be set to zero. } PTHD; PTHD_OLD is identical, with 'LONG' replaced by 'WORD' 'flags' bits: #define PTHF_NEWPATH 0x01 // flag - spline editor path #define PTHF_CONNECTIN 0x02 // flag - 'infrom' valid #define PTHF_CONNECTOUT 0x04 // flag - 'outto' valid #define PTHF_SHARP 0x80 // flag - discontinuous knot Prior to the introduction of Imagine's spline editor, the path objects were all "axis based", and a path was just a series of axis objects. The axis position, the 3 direction vectors, and the axis lengths were stored in the 'TFORM' structures, and the Y axis length had/has a special significance. For "open paths", the Y axis length of the last axis object is zero. All other Y axis lengths are non-zero, and correspond to the length of the path as it runs from that axis, to the next. When the spline editor was added to Imagine, the path data was extended to allow for more options. For detail and stage editor paths, the "axis" data remained unchanged (note: the first 5 members of the PTHD structure are the same as a TFORM structure), and the information about the "connection order" was added to the data ... however, the connection order is always "first to last" (i.e. axis 0 connects to axis 1, then 1 to 2, etc.) PTHD structure: The PTHD structures are used to describe two types of paths. The first type is used for detail and stage editor "paths", where path "axes" appear in various places in the world, the the directions of the Y axes are used to establish a path. The second type is used to describe "spline paths" used by the "spline" editor. The "spline editor" paths have the 'PTHF_NEWPATH' flag set in the 'flags' member. Both types use the 'infrom' and 'outto' fields, along with the 'PTHF_CONNECTIN' and 'PTHF_CONNECTOUT' flags to describe the "connection" order. When PTHF_CONNECTIN is set, for example, the 'infrom' field is considered as valid, and contains the axis (or spline knot) number of the axis (or knot) preceding the current one in the connection order. Spline editor paths allow multiple loops in a single object's path data, and "work in progress" spline paths can have many knots which are connected only on one end. Detail and Stage editor paths allow only a single loop in the path (Closed Path), or two endpoints (Open Path). The 'r' vector in the PTHD structure is always the position of the axis or knot. The use of the other VECTOR fields depends on the type of path. For Detail/Stage editor paths: 'a' - is the X axis direction (a unit vector) 'b' - is the Y axis direction (a unit vector) 'c' - is the Z axis direction (a unit vector) 's.X' - length of X axis 's.Z' - length of Z axis 's.Y' - path length on "outgoing path" to next axis (note: if you are reading a file generated by Imagine, this field will be valid. If you are generating a file yourself, then you will need more information. For a "quick hack", you can write any non-zero number in this field, and load the path into the detail editor, and "tweak" each axis, to get it calculated. Also, it should be possible to use such a path in the "Stage Editor". For use in the Detail editor, though, it is important that this value be set correctly. At the time of this writing, there is no existing document explaining the algorithm that is used. If it becomes important, contact Impulse.) For Spline editor paths: Each point (knot) on the path is associated with two "control points" ... the "bowtie" points in the editor ... one on each side of the knot. The path is assumed to lie in the X-Z plane, with the Y components of every vector being zero. 'a' - is the direction from the knot to the control point preceding it (a unit vector) 'c' - is the direction from the knot to the control point following it (a unit vector) 'b' - is the Y axis direction (0,1,0) (perpendicular to the plane containing the path) 'c' - is the Z axis direction (a unit vector) 's.X' - distance from the knot to the preceding control point 's.Z' - distance from the knot to the following control point 's.Y' - unused - set to zero. Note: Zeros should be written for directions & distances at open ends of the path (where one of PTHF_CONNECTIN or PTHF_CONNECTOUT is not set). If PTHF_SHARP is clear, the 'a' and 'c' vectors should point in opposing directions (continuous tangent vector at the knot) ... otherwise (if PTHF_SHARP is set), they can point in different directions, and the path will have a sharp change of direction at the point. Note 2: on path lengths and Y axis lengths for "axis based" paths. The actual path that is generated internally in Imagine, is a 3rd order "b-spline path". For b-spline pros, the two control points between a pair of axes, are displaced from the axes, in the direction of the Y-axis (unit) vectors, by a distance which is 1/3 of the Y axis length. A recursive algorithm, and "initial guess" formula are used to adjust the Y axis length so that the path which is generated by the above procedure, in fact has a length equal to the Y axis length. When a point is to be placed at, say a 30% point along the path, the "s = .3, 1-s = .7" point of the b-spline is used. It is an approximation to the point which is 30% along the actual path length, but it's a fairly good approximation, due to the fact that the "velocity vector" at the two endpoints has a length equal to the path length, via the fact that the control points are displaced by 1/3 the path length, and the fact that the average of the length of the velocity vector, over the range of 's' range is, by definition, the actual path length. FORD - size 56 + 12 * PC FOR2 - size 56 + 12 * PC + 2 * sections FOR3 - size 62 + 12 * PC + 4 * sections - 32K limit removed These chunks contain data for Imagine "forms editor" objects. (FORD chunk) - "two formers" style only WORD NumC; ; number of cross section points WORD NumF; ; number of slices WORD Flags; ; orientation flag WORD pad; ; reserved - set to zero MATRIX TForm; ; object rotation/scaling transformation VECTOR Shift; ; object translation VECTOR Points[PC]; ; "Forms" editor points (FOR2 chunk) - more styles added, and multiple cross sections WORD NumC; ; number of cross section points WORD NumF; ; number of slices WORD Flags; ; orientation flag WORD NumS; ; cross section count MATRIX TForm; ; object rotation/scaling transformation VECTOR Shift; ; object translation VECTOR Points[PC]; ; "Forms" editor points (FOR3 chunk) - 32K limit removed DWORD NumC; ; number of cross section points DWORD NumF; ; number of slices DWORD NumS; ; cross section count WORD Flags; ; orientation flag MATRIX TForm; ; object rotation/scaling transformation VECTOR Shift; ; object translation VECTOR Points[PC]; ; "Forms" editor points Flags bits: bit 0: orientation flag #define FORM_VFORM 1 ; X-Y orientation for cross sections bits 1-2: type bits (FOR2 and FOR3 chunks only) #define FORM_TWOF 0 ; "Two formers" style (PPF = 4, below) #define FORM_ONEF 2 ; "One former" style (PPF = 2, below) #define FORM_ONES 4 ; "One spacer" style (PPF = 1, below) #define FORM_TYPE 6 ; - mask for above For Imagine's "Forms" objects, the "PNTS" chunk above is not written out, but this structure is written instead. The point count is PC = NumS * NumC + PPF * NumF, where 'NumS' is set to 1 for data in FORD chunks. The object's real points are then calculated from these using a proprietary algorithm. The tranformation parameters above allow the axes of the real object be moved around relative to the "Forms" points. ANID - size 64 LONG Cellno; ; cell number TFORM TForm; ; object position/axes/size in that cell. For Imagine's "Cycle editor" objects, within EACH DESC chunk in the file - that is, for each object of the group, there will be a series of ANID chunks. The cell number sequences of each child of a group must agree with the sequence for the head object, and the first cell number must be zero. Note: the "cycle editor" was removed in Imagine 1.0 for Windows. DESC sub-sub-chunks - object "state" data ----------------------------------------- State data in DESC blocks is stored as multiple successive STND chunks, one for each state, each containing sub-chunks. A STID sub-chunk names the state and specifies certain flag values, and then multiple STDT sub-chunks can appear, each containing a specific type of data. STND - variable size STID chunk ; need not appear first STDT chunk STDT chunk ... etc. STID - size 20 BYTE Name[18]; ; state name - null terminated WORD Flags; ; state flags Flag bits: SNF_AXES 0x0001 ; contains axis data SNF_SHAPE 0x0002 ; contains point/path data SNF_COLOR 0x0004 ; contains face color data SNF_PROPS 0x0008 ; contains attributes data SNF_TXBR 0x0010 ; contains brush or texture data Imagine uses these flags to quickly determine which types of data are associated with a (named) state. STDT - variable size WORD IdTag; ; indicates the type of data WORD Flags; ; reserved, set to zero. BYTE Data[] ; specific data The IdTag values, and data types are listed below. The chunks can appear in any order, with the following exception: a SDTAG_TXBRNAME chunk is always followed a chunk containing texture or brush data. Some of the types have been upgraded, to allow for the new features that have been added in Imagine. SDTAG_OBJAXES 101 // object axes, etc. : TFORM structure SDTAG_POINTS 102 // point coords : VECTOR list SDTAG_PAXES 103 // path axes : PTHD_OLD list SDTAG_SIZES 104 // object axis sizes : VECTOR SDTAG_DLIST 105 // diffuse colors : BYTE[3] list SDTAG_TLIST 106 // filter colors : BYTE[3] list SDTAG_RLIST 107 // reflection colors : BYTE[3] list SDTAG_OPROPS 108 // object colors/props: OPROPS structure SDTAG_TXBRNAME 109 // name field for next brush or texture SDTAG_OBRSH 110 // brush data : OBRSH structure SDTAG_OTXTR 111 // texture data : OTXTR structure SDTAG_OBRSH2 112 // brush data : OBRSH2 structure SDTAG_OTXTR2 113 // brush data : OTXTR2 structure SDTAG_OPROPS2 114 // object colors/props: OPROPS2 structure SDTAG_OPROPS3 115 // object colors/props: OPROPS3 structure SDTAG_PAXES2 116 // path axes : PTHD list upgrade replacements: SDTAG_OBRSH2 replaces SDTAG_OBRSH. SDTAG_OTXTR2 replaces SDTAG_OTXTR. SDTAG_OPROPS3 replaces SDTAG_OPROPS2 and SDTAG_OPROPS. The items containing "per face color lists" contain 3 bytes per object face. The SDTAG_POINTS chunk contains one 12 bytes per object point. The SDTAG_PAXES and SDTAG_PAXES2 chunks contain one structure (PTHD_OLD or PTHD) per path axis. The SDTAG_TXBRNAME chunk contains a byte count followed by a the characters in the file or module name. In general, the string is not null terminated. However, the chunk size is forced to be even, by appending a zero pad byte - which is counted in the chunk size, in this case (contratictory to the normal way that filenames are handled above, in the non-state-based data). The OBRSH,OTXTR,OBRSH2 and OTXTR2 structure are defined below. For details on the items in the structures, refer to the descriptions for the TXT1 and BRS1 chunks (and successors). typedef struct { TFORM tform; // 60 bytes WORD type; // 2 bytes WORD wrap; // 2 bytes WORD fullscale; // 2 bytes WORD maxseq; // 2 bytes BYTE subgrp[18]; // 18 bytes BYTE stname[18]; // 18 bytes } OBRSH; // total size = 104 typedef struct { TFORM tform; // 60 bytes WORD type; // 2 bytes WORD wrap; // 2 bytes WORD fullscale; // 2 bytes WORD maxseq; // 2 bytes BYTE subgrp[18]; // 18 bytes BYTE stname[18]; // 18 bytes BYTE brusrid[18]; // 18 bytes FRACT brshint; // 4 bytes FRACT brfog_low; // 4 bytes FRACT brfog_hi; // 4 bytes } OBRSH2; // total size = 134 typedef struct { TFORM tform; // 60 bytes WORD flags; // 2 bytes WORD pad; // 2 bytes FRACT params[16]; // 64 bytes BYTE pflags[16]; // 16 bytes BYTE subgrp[18]; // 18 bytes BYTE stname[18]; // 18 bytes } OTXTR; // total size = 180 typedef struct { TFORM tform; // 60 bytes WORD flags; // 2 bytes WORD pad; // 2 bytes FRACT params[16]; // 64 bytes BYTE pflags[16]; // 16 bytes BYTE subgrp[18]; // 18 bytes BYTE stname[18]; // 18 bytes BYTE txusrid[18]; // 18 bytes FRACT txtrint; // 4 bytes } OTXTR2; // total size = 202 // the OPROPS,OPROPS2 and OPROPS3 structures are defined // as follows: typedef struct { BYTE props[NUM_IOBJ_PROPS]; // 8 bytes WORD lamp; // 2 bytes WORD flags; /* unused */ // 2 bytes VECTOR intensity; // 12 bytes FRACT foglen; // 4 bytes BYTE diffuse[4]; // 4 bytes (0,R,G,B) BYTE reflect[4]; // 4 bytes (0,R,G,B) BYTE transmit[4]; // 4 bytes (0,R,G,B) BYTE specular[4]; // 4 bytes (0,R,G,B) } OPROPS; // 42 bytes total typedef struct { BYTE props[NUM_IOBJ_PROPS]; // 8 bytes WORD lamp; // 2 bytes WORD flags; /* unused */ // 2 bytes VECTOR intensity; // 12 bytes FRACT foglen; // 4 bytes BYTE diffuse[4]; // 4 bytes (0,R,G,B) BYTE reflect[4]; // 4 bytes (0,R,G,B) BYTE transmit[4]; // 4 bytes (0,R,G,B) BYTE specular[4]; // 4 bytes (0,R,G,B) FRACT fogfoff; // 4 bytes FRACT foghot; // 4 bytes WORD fogtype; // 2 bytes WORD fogpad; // 2 bytes } OPROPS2; // 50 bytes total typedef struct { BYTE props[NUM_IOBJ_PROPS]; // 8 bytes WORD lamp; // 2 bytes WORD flags; /* unused */ // 2 bytes VECTOR intensity; // 12 bytes FRACT foglen; // 4 bytes BYTE diffuse[4]; // 4 bytes (0,R,G,B) BYTE reflect[4]; // 4 bytes (0,R,G,B) BYTE transmit[4]; // 4 bytes (0,R,G,B) BYTE specular[4]; // 4 bytes (0,R,G,B) FRACT fogfoff; // 4 bytes FRACT foghot; // 4 bytes WORD fogtype; // 2 bytes WORD fogpad; // 2 bytes FRACT overdfog; // 4 bytes FRACT overdspec; // 4 bytes } OPROPS3; // 50 bytes total The data in these structures corresponds to "normal" data for objects (described elsewhere) as follows: props[NUM_IOBJ_PROPS]; - PRP2 chunk WORD lamp; - SHP2 chunk - Lamp VECTOR intensity; - INT1 chunk FRACT foglen; - FOGL/FOG2/FOG3 chunks - Foglen BYTE diffuse[4]; - COLR chunk BYTE reflect[4]; - REFL chunk BYTE transmit[4]; - TRAN chunk BYTE specular[4]; - SPC1/SPC2 chunks - Color FRACT fogfoff; - FOG2/FOG3 chunks - Falloff FRACT foghot; - FOG2/FOG3 chunks - Hotness WORD fogtype; - FOG2/FOG3 chunks - Type FRACT overdfog; - FOG3 chunk - Overdrive FRACT overdspec; - SPC2 chunk - Overdrive End ---